﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace COFE.Core.Utils
{
    /// <summary>
    /// Enum related utils.
    /// </summary>
    /// <typeparam name="A">Type of the enums.</typeparam>
    public static class EnumUtils<T>
    {
        public static Object[] AddProperties()
        {
            List<object> retList = new List<object>();

            foreach (var item in Enum.GetValues(typeof(T)))
                retList.Add(item);

            return retList.ToArray();
        }

        public static T Parse(object property)
        {
            return (T)property;
        }

        public static T Parse(string property)
        {
            return (T)Enum.Parse(typeof(T), property);
        }


        private static Dictionary<object, T> cacheAttributeDic = new Dictionary<object, T>();

        /// <summary>
        /// Find the specific attribute from object.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T FindAttribute(object obj)
        {
            lock (cacheAttributeDic)
            {
                if (cacheAttributeDic.ContainsKey(obj))
                    return cacheAttributeDic[obj];

                T retVal = default(T);

                foreach (var attribute in
                    obj.GetType().GetField(
                        obj.ToString()).GetCustomAttributes(typeof(T), false))
                {
                    retVal = (T)attribute;
                    break;
                }

                cacheAttributeDic.Add(obj, retVal);

                return retVal;
            }
        }

        /// <summary>
        /// Given a set of properties, return a list of properties that support the attribute T, as well as the filterStr method.
        /// </summary>
        /// <param name="properties"></param>
        /// <param name="filterMethod"></param>
        /// <returns></returns>
        public static object[] FilterPropertiesForAttribute(object[] properties, Func<T, bool> filterMethod)
        {
            List<object> retList = new List<object>();

            foreach (object item in properties)
            {
                T attribute = FindAttribute(item);
                if (attribute != null && filterMethod(attribute))
                    retList.Add(item);
            }

            return retList.ToArray();
        }

        /// <summary>
        /// Given a set of properties, return a list of properties that support the attribute T.
        /// </summary>
        /// <param name="properties"></param>
        /// <returns></returns>
        public static object[] FilterPropertiesForAttribute(object[] properties)
        {
            return FilterPropertiesForAttribute(properties, (a) => { return true; });
        }

        /// <summary>
        /// Taken from Minon's Blog 2.0
        /// http://mironabramson.com/blog/category/C.aspx?page=2
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="strType"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool EnumTryParse(string strType, out T result)
        {
            string strTypeFixed = strType.Replace(' ', '_');
            if (Enum.IsDefined(typeof(T), strTypeFixed))
            {
                result = (T)Enum.Parse(typeof(T), strTypeFixed, true);
                return true;
            }
            else
            {
                foreach (string value in Enum.GetNames(typeof(T)))
                {
                    if (value.Equals(strTypeFixed, StringComparison.OrdinalIgnoreCase))
                    {
                        result = (T)Enum.Parse(typeof(T), value);
                        return true;
                    }
                }
                result = default(T);
                return false;
            }
        }

    }

    /// <summary>
    /// Enum related Utils.
    /// </summary>
    public static class EnumUtils
    {
        /// <summary>
        /// Get name of resource of a property. Resource is an attribute that's tag a property.
        /// e.g. IconProperties.Icon
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string GetResourceName(object property, bool fullQualifiedName = true)
        {
            if (!fullQualifiedName)
                return property.ToString();

            if (AliasExtension.IsMetadata(property))
                return AliasExtension.getAlias(property);
            
            return EnumUtils.GetFullName(property);
        }


        public static string GetFullName(object enumItem)
        {
            return String.Format("{0}.{1}", enumItem.GetType().Name, enumItem.ToString());
        }


     

    }
}
